/****************************************************************************
 *  _____       ______  _____
 * |_   _|     |  ____|/ ____|
 *   | |  _ __ | |__  | (___    Institute of Embedded Systems
 *   | | | '_ \|  __|  \___ \   Zürcher Hochschule für Angewandte
 *  _| |_| | | | |____ ____) |  Wissenschaften
 * |_____|_| |_|______|_____/   8401 Winterthur, Switzerland
 *
 ****************************************************************************
 *
 * @version $Rev: 209 $
 * @author  $Author: bacr $
 * @date    $Date: 2014-01-09 10:44:54 +0100 (jeu., 09 janv. 2014) $
 *
 ***************************************************************************/

#ifndef __PTP2_BMC_ALGORITHM_H__
#define __PTP2_BMC_ALGORITHM_H__

typedef struct ptp2_bmc_algorithm_t             ptp2_bmc_algorithm_t;
typedef enum   ptp2_bmc_algorithm_profile_t     ptp2_bmc_algorithm_profile_t;

#include "object.h"

#include "hcpp/ptp2_datasets.h"
#include "hcpp/ptp2_port.h"
#include "packet/packet.h"

enum ptp2_bmc_algorithm_profile_t {
    PTP2_BMC_ALGORITHM_PROFILE_DEFAULT,
    PTP2_BMC_ALGORITHM_PROFILE_ITU_T_G_8265_1,
    PTP2_BMC_ALGORITHM_PROFILE_ITU_T_G_8275_1
};

struct ptp2_bmc_algorithm_t {
    object_t                    obj;

    /* ptp2 master */
    ptp2_master_t              *master;
    ptp2_foreign_master_ds_t   *e_best;

    uint16_t                    foreign_master_count;
    uint8_t                     announce_receipt_timeout_counter;       /**< 9.2.6.11 counter for ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES */
    uint8_t                     foreign_master_time_window_counter;     /**< 9.3.2.4.4 counter for FOREIGN_MASTER_TIME_WINDOW */

    ptp2_task_t                 task_state_decision_event;

    uint16_t                    (*compute_er_best)                  (ptp2_bmc_algorithm_t *this, ptp2_port_t *port);
    void                        (*state_decision_algorithm)         (ptp2_bmc_algorithm_t *this, ptp2_master_t *master, ptp2_port_t *port);
    ptp2_bmc_algorithm_result_t (*dataset_comparison_algorithm)     (ptp2_foreign_master_ds_t *a, ptp2_foreign_master_ds_t *b);
};


bool                        ptp2_bmc_algorithm_init                             (ptp2_bmc_algorithm_t *this, ptp2_master_t *master);
void                        ptp2_bmc_algorithm_set_profile                      (ptp2_bmc_algorithm_t *this, ptp2_bmc_algorithm_profile_t profile);
void                        ptp2_bmc_algorithm_announce_receipt_timer_restart   (ptp2_bmc_algorithm_t *this);
void                        ptp2_bmc_algorithm_update_s1                        (ptp2_master_t *master, ptp2_foreign_master_ds_t *fm_ds);
void                        ptp2_bmc_algorithm_update_m1_m2                     (ptp2_master_t *master);
void                        ptp2_bmc_algorithm_convert_to_foreign_master_ds     (ptp2_default_ds_t *default_ds, ptp2_foreign_master_ds_t *default_fm);

#endif

